/*                                          *
* abandon hope, all ye who enter here       *
* author: gregory nicholas                  *
* uri: www.phasedreduction.com              *
*                                           *
* some scripts written specifically for     *
* the phasedreduction.com website           *
*			                                *
*                                           */
Site = {
	Regions: {
		'Page': $('page'),
		'PageWrapper': $('page-wrapper'),
		'PageBody': $('page-body')
	},
	init: function(Config) {
		this.Guid = 'Site';
		this.Regions.Page.removeClassName('pre-loading');
		this.Regions.Page.appear({ duration: 1, afterFinish: function() {
			Phased.Controls.Tooltips.LoadItems();
			Phased.Controls.TabSets.Items.Add(new Phased.Controls.TabSets.TabSet({
				'Id': 'body-a',
				'InSpeed': 1.2,
				'OutSpeed': 0.15
			}));
		}});
		
		/*
		Event.KEY_RETURN
		Event.KEY_ESC
		Event.KEY_LEFT
		Event.KEY_UP
		Event.KEY_RIGHT
		Event.KEY_DOWN
		KEY_BACKSPACE: 8,
		KEY_TAB: 9,
		KEY_DELETE: 46,
		*/
		Object.extend(Event, {
			KEY_ENTER: 13,
			KEY_SHIFT: 16,
			KEY_CTRL: 17,
			KEY_ALT: 18,
			KEY_CAPS: 20,
			KEY_ESCAPE: 27,
			KEY_PAGE_E: 33,
			KEY_PAGE_D: 34,
			KEY_END: 35,
			KEY_HOME: 36,
			KEY_ARROW_L: 37,
			KEY_ARROW_U: 38,
			KEY_ARROW_R: 39,
			KEY_ARROW_D: 40,
			KEY_INSERT: 45,
			KEY_WINDOWS: 91,
			KEY_A: 65,
			KEY_Z: 90
		});
		this.Config = Config || {};
		this.Id = this.Config.Id || '';
		this.Title = this.Config.Title || '';
		this.initListeners();
        this.Notifier = this.Notifiers.Create();
        this.ScorecardValue = 0;
        this.ScorecardAgeValue = 0;
        
		this.FormItems = [];
		$$('.phased-form').each(function(el) {
			var f = new this.FormBase(el);
			var p = this.FormItems.push(f);
			f.callback_success = this.CalculateSave;
		}.bind(this));
	},
	Show: function() {
		this.Regions.Page.removeClassName('pre-loading');
		this.Regions.PageWrapper.appear({ duration: 0.3 });
	},
	TrackClick: function(e) {
		if (!e && !e.element) {
			return true;
		}
		var El = e.element();
		var Category = 'User.Click.' + (El.readAttribute('guid') || El.identify());
		var Name = El.readAttribute('href') || El.readAttribute('id') || El.innerHTML.stripTags().truncate();
		var Value = App.User.UserName;
			Phased.Controls.Analytics.Events.Add(
				new Phased.Controls.Analytics.Event(Category, Name, Value)
			);
	},
	initListeners: function() {
		Event.observe(document, 'click', this.TrackClick.bind(this));
		Event.observe(document, 'keydown', this.KeyHandler.bind(this));
		Event.observe(window, 'unload', function() {
			document.stopObserving();
		});
	},
	initFieldForm: function(el) {
		if (!Object.isElement(el)) {
			return false;
		}
        document.fire('control:form-submit', {
        	formel: el.up('.phased-form'),
        	fieldel: el,
        	action: 'submit'
        });
	},
	isFormElement: function(el) {
		if (!Object.isElement(el)) {
			return false;
		}
		var tn = el.tagName.toUpperCase();
		return (tn === 'INPUT' || tn === 'SELECT' || tn === 'TEXTAREA');
	},
	KeyHandler: function(e) {
		if (this.isProcessing) {
			e.stop();
			return false;
		}
		if (!e || !Object.isElement(e.target)) {
			return false;
		}
		var c = e.keyCode || e.which;
		var $el = $(e.target);
		var ft = ($el.readAttribute('field-type') || '').toUpperCase();
		var tn = ($el.tagName || '').toUpperCase();
		switch (true) {
			case (c === Event.KEY_ESCAPE):
				$el.blur();
				break;
			/* Enter Key, Shift+Enter for TEXTAREA */
			case (c === Event.KEY_RETURN):
				if (tn === 'TEXTAREA' && e.shiftKey) {
					e.stop();
					this.initFieldForm($el);
					return;
				} else if (this.isFormElement($el)) {
					e.stop();
					this.initFieldForm($el);
					return;
				}
				break;
			/* Integer Form Field */
			case (c >= Event.KEY_A && c <= Event.KEY_Z):
				if (this.isFormElement($el) && ft === 'INTEGER') {
					//TODO: Fire validation event error
					e.stop();
					return false;
				}
				break;
		}
	},
	CalculateScorecardAge: function() {
		var v = 0;
		var f = $('patient-age');
		if (!$('patient-age').getValue().blank()) {
			var a = parseInt($('patient-age').getValue(), 10);
			if (a < 65) {
				v = 0;
			}
			if (a > 64 && a - 75) {
				v = 2;
			}
			if (a >= 75) {
				v = 3;
			}
		}
		Site.ScorecardValue -= Site.ScorecardAgeValue;
		Site.ScorecardAgeValue = v;
		Site.ScorecardValue += Site.ScorecardAgeValue;
		$('scorecard-results').update('Current Stratification Score: <span>' + Site.ScorecardValue + '</span>');
	},
	CalculateScorecard: function(ref, fieldId, value) {
		$(ref).up().toggleClassName('true');
		var f = $(fieldId);
		f.value = (f.value === 'true') ? 'false': 'true';
		if (f.value === 'true') {
			Site.ScorecardValue -= value;
		} else {
			Site.ScorecardValue += value;
		}
		$('scorecard-results').update('Current Stratification Score: <span>' + Site.ScorecardValue + '</span>');
		
	},
	CalculateSave: function() {
		$('form-patient-add').fade({ duration: 0.5, to: 0.2 });
		$('status-msg-success').appear({ duration: 0.7, afterFinish: function() {
			$('form-patient-add').appear({ duration: 1, delay: 1.5 });
			$('status-msg-success').fade({ duration: 0.7, delay: 1.5 });
		}});
	}
};



Site.Notifiers = {
	Create: function(Config) {
		Config = Config || {};
		Config.Id = Config.Id || 'page-indicator';
        var el = new Element('div', { 'id': Config.Id, 'class': 'page-indicator', 'style': 'display:none;' });
        Element.insert(document.body, { bottom: el });
		return el;
	},
	Position: function(Indicator, Container, Config) {
		var el = Indicator || $('page-indicator');
		if (!Object.isElement(el)) {
			return;
		}
		var cn = Container || document.viewport;
        var elDims = el.getDimensions();
        var cnDims = cn.getDimensions();
        if (cn.style && cn.style.position !== 'absolute') {
        	//cn.relativize();
        }
        el.setStyle({
        	top: ((cnDims.height/2) - (elDims.height/2)) + 'px',
        	left: ((cnDims.width/2) - (elDims.width/2)) + 'px'
        });
	},
	Show: function(Indicator, Container, Config) {
		var el = Indicator || $('page-indicator');
		if (!Object.isElement(el)) {
			return;
		}
        this.Position(el);
		el.setOpacity(0);
        el.appear({ duration: 0.15 });
	},
	Hide: function(Indicator) {
		var el = Indicator || $('page-indicator');
		if (!Object.isElement(el)) {
			return;
		}
		el.hide();
	}
};



Site.FormBase = Class.create({
    el: Object,
    label: String,
    method: String,
    enctype: String,
    notifier: null,
    fields: null,
    errors: null,
    error: null,
    request: Object,
    data: Object,
    parameters: Object,
    ajax_uri: null,
    callback_init: null,
    callback_failure: null,
    callback_success: null,
    initialize: function(el) {
        this.el = el;
        this.id = this.el.identify();
        if (this.el.readAttribute('ajax-uri')) {
            this.ajax_uri = this.el.readAttribute('ajax-uri');
        }
        if (this.el.readAttribute('label')) {
            this.label = this.el.readAttribute('label');
        }
        if (this.el.readAttribute('method')) {
            this.method = this.el.readAttribute('method').toLowerCase();
        }
        if (this.el.readAttribute('enctype')) {
            this.enctype = this.el.readAttribute('enctype').toLowerCase();
        }
        if (this.el.readAttribute('callback_init')) {
            this.callback_init = this.el.readAttribute('callback_init');
        }
        if (this.el.readAttribute('callback_failure')) {
            this.callback_failure = this.el.readAttribute('callback_failure');
        }
        if (this.el.readAttribute('callback_success')) {
            this.callback_success = this.el.readAttribute('callback_success');
        }
        if (this.el.readAttribute('notifier')) {
            if ($(this.el.readAttribute('notifier'))) {
                this.notifier = $(this.el.readAttribute('notifier'));
            }
        }
        document.observe("control:form-submit", function(e) {
    		if (e.memo.formel.identify() === this.id) {
    			e.stop();
    			this.submit();
    		}
    	}.bind(this));
		this.el.observe('submit', function(e) {
    		return this.submit();
    	});
        this.loadHandlers();
    },
    loadHandlers: function() {
        this.handlers = [];
        $$('.form-handler[form="' + this.el.id + '"]').each(function(el) {
            this.handlers.push(new FormHandler(this, el));
        }.bind(this));
        this.loadFields();
    },
    submit: function(e) {
        if (App.isProcessing) {
        	return;
        }
        App.isProcessing = true;
        if (e && e.stop) {
        	e.stop();
        }
    	if (document.activeElement && document.activeElement.blur) {
    		document.activeElement.blur();
    	}
        this.el.setOpacity(0.3);
        this.el.select('.form-errors').invoke('hide');
        if (this.notifier) {
            Site.Notifiers.Position(this.notifier, this.notifier.up());
            this.notifier.show();
        }
        if (!Object.isString(this.ajax_uri)) {
        	this.el.submit();
            return true;
        }
        
        //TODO: make form elements readonly
        
        if (this.callback_init) {
            if (Object.isFunction(this.callback_init)) {
                this.callback_init();
            } else if (typeof(this.callback_init) === 'string') {
                eval(this.callback_init);
            }
        }
        this.loadFields();
        this.clearErrors();
        if (! this.validate()) {
            this.el.appear({ duration: 0.3 });
            App.isProcessing = false;
            this.onError('testing');
            return;
        }
        this.fields.each(function(field) {
            var InputType = field.el.readAttribute('type') || '';
            var InputName = field.el.readAttribute('name') || '';
            var InputId = field.el.id || field.el.indentify();
            switch(InputType) {
            	case 'hidden':
                	this.parameters[InputName] = field.el.getValue();
            		break;
            	case 'checkbox':
            		this.parameters[InputName] = $F(field.el.id);
            		break;
            	case 'radio':
	                if (field.el.checked) {
	                    this.parameters[InputName] = $F(field.el.id);
	                }
            		break;
            	default:
            		var hasvalue = true;
	                if (!field.defaultvalue.blank()) {
	                    if (field.defaultvalue === field.el.getValue()) {
	                        hasvalue = false;
	                    }
	                }
	                if (hasvalue) {
	                    this.parameters[InputName] = field.el.getValue();
	                }
            		break;
            }
        }.bind(this));
        if (this.ajax_uri) {
            var query = '&';
            if (this.el.readAttribute('ajax-uri-query')) {
                query += this.el.readAttribute('ajax-uri-query');
            }
            this.request = new Ajax.Request(this.ajax_uri, {
                evalScripts: true,
                synchronous: true,
                method: this.method,
                onSuccess: this.callback.bind(this),
                onFailure: function(e) {
                	App.isProcessing = false;
                    alert('Error occurred during form submission: ' + e.responseText);
                }.bind(this),
                parameters: this.parameters
            });
        	return false;
        } else {
            this.el.submit();
            return true;
        }
    },
    validate: function() {
        this.clearErrors();
        var hasError = false;
        this.fields.each(function(field) {
            field.el.removeClassName('error');
            if (! field.validate()) {
                hasError = true;
                field.el.addClassName('error');
            }
        }.bind(this));
        if (hasError) {
            if (this.callback_failure) {
                if (Object.isFunction(this.callback_failure)) {
                    this.callback_failure();
                } else if (typeof(this.callback_failure) === 'string') {
                    eval(this.callback_failure);
                }
            }
            this.onError();
        } else {
            return true;
        }
    },
    callback: function(response) {
    	App.isProcessing = false;
        try {
            this.data = eval(response.responseText);
        } catch (ex) {
            alert(ex + ': ' + response.responseText);
        }
        if (this.Status == 'Error') {
            if (this.callback_failure) {
                if (Object.isFunction(this.callback_failure)) {
                    this.callback_failure();
                } else if (typeof(this.callback_failure) === 'string') {
                    eval(this.callback_failure);
                }
            }
            this.onError(this.data.result.message);
        } else {
            this.onSuccess();
        }
    },
    loadFields: function() {
        this.clearFields();
        this.fields = [];
        this.el.select('.form-field').each(function(El) {
            El.writeAttribute('errormsg', '');
            if ($('field-error-' + El.id)) {
                $('field-error-' + El.id).remove();
            }
            this.fields.push(new FormField(this, El));
        }.bind(this));
    },
    clearFields: function() {
        if (this.fields) {
            this.fields.each(function(El) {
                El = null;
            });
            this.fields.clear();
        }
    },
    hasError: function() {
        if (this.error) {
            return true;
        }
    },
    clearErrors: function() {
        if (this.errors) {
            this.errors.each(function(error) {
                error = null;
            });
            this.errors.clear();
        }
        this.errors = [];
        if (this.hasError()) {
            this.error.remove();
            this.error = null;
        }
        $$('#' + this.el.id + ' .field-error').each(function(errorel) {
            errorel.remove();
        });
    },
    onError: function(msg) {
        if (this.notifier) {
            this.notifier.hide();
        }
        this.clearErrors();
        this.error = new Element('div', { 'class': 'form-errors', 'style': 'display:none;' });
        //TODO: Garbage
        this.error.update('<h3>' + this.label + ' Failed</h3>');
        $$('#' + this.el.id + ' .error').each(function(ef) {
            var e = new FormError(this.error, ef);
            e.render();
            this.errors.push(e);
        }.bind(this));
        this.el.insert({ top: this.error });
        this.error.appear({ duration: 0.3 });
    },
    onSuccess: function() {
        this.el.setOpacity(1);
        if (this.notifier) {
            this.notifier.fade({ duration: 0.3 });
        }
        if (this.callback_success) {
            if (Object.isFunction(this.callback_success)) {
                this.callback_success();
            } else if (typeof(this.callback_success) === 'string') {
                eval(this.callback_success);
            }
        }
    }
});

FormField = Class.create({
    el: null,
    form: null,
    fieldtype: null,
    required: false,
    matchfield: null,
    maxlength: null,
    minlength: null,
    label: null,
    dovalidate: true,
    value: null,
    autocompleter: null,
    defaultvalue: '',
    initialize: function(form, el) {
        this.form = form;
        this.el = $(el);
        this.id = this.el.identify();
        if (this.el.readAttribute('required') === '1') {
            this.required = true;
        }
        if (this.el.readAttribute('field-type')) {
            this.fieldtype = this.el.readAttribute('field-type');
        }
        if (this.el.readAttribute('maxlength')) {
            this.maxlength = parseInt(this.el.readAttribute('maxlength'));
        }
        if (this.el.readAttribute('minlength')) {
            this.minlength = parseInt(this.el.readAttribute('minlength'));
        }
        if (this.el.readAttribute('label')) {
            this.label = this.el.readAttribute('label');
        }
        if (this.el.readAttribute('matchfield')) {
            this.matchfield = $(this.el.readAttribute('matchfield'));
        }
        if (this.el.readAttribute('validate')) {
            this.dovalidate = (this.el.readAttribute('validate') === 'false') ? false: true;
        }
        if (this.el.readAttribute('def-value')) {
            this.defaultvalue = this.el.readAttribute('def-value');
            if (this.el.getValue().blank()) {
                this.el.value = this.defaultvalue;
                this.el.addClassName('inactive');
            }
        }
        this.el.observe('focus', this.focus.bind(this));
        this.el.observe('blur', this.blur.bind(this));
    },
    validate: function() {
        if (! this.dovalidate) {
            return true;
        }
        this.value = this.el.getValue();
        var length = (this.value) ? this.value.length: 0;
        if (this.required) {
            if (!this.value) {
                return false;
            }
            if (this.value.toLowerCase() === this.defaultvalue.toLowerCase() || this.value.blank()) {
                this.el.writeAttribute('errormsg', this.label + ' cannot be blank.');
                this.errormsg = this.label + ' cannot be blank.';
                return false;
            }
        } else {
            if (!this.value) {
                return true;
            }
            if (this.value.blank()) {
                return true;
            }
        }
        if (this.maxlength) {
            if (length < this.minlength) {
                this.el.writeAttribute('errormsg', this.label + ' must be longer than ' + this.minlength + ' characters.');
                this.errormsg = this.label + ' must be longer than ' + this.minlength + ' characters.';
                return false;
            }
        }
        if (this.minlength) {
            if (length < this.minlength) {
                this.el.writeAttribute('errormsg', this.label + ' must be smaller than ' + this.maxlength + ' characters.');
                this.errormsg = this.label + ' must be smaller than ' + this.maxlength + ' characters.';
                return false;
            }
        }
        if (this.matchfield) {
            matchvalue = this.matchfield.getValue();
            if (matchvalue !== this.value) {
                var msg = this.label + ' must match ' + this.matchfield.readAttribute('label') + '.';
                this.el.writeAttribute('errormsg', msg);
                this.errormsg = msg;
                this.matchfield.addClassName('error');
                return false;
            }
        }
        return true;
    },
    focus: function(e) {
        this.el.removeClassName('inactive');
        this.el.removeClassName('error');
        this.el.addClassName('focus');
        if (!this.defaultvalue.blank()) {
            this.el.value = (this.el.value === this.el.readAttribute('def-value')) ? '': this.el.getValue();
        }
        if ($('field-error-' + this.el.id)) {
            $('field-error-' + this.el.id).remove();
        }
    },
    blur: function(e) {
        if (this.el.getValue().blank()) {
            this.el.addClassName('inactive');
        }
        if (this.defaultvalue !== '') {
            this.el.value = (this.el.getValue().blank()) ? this.el.readAttribute('def-value'): this.el.getValue();
        }
        if ($('field-error-' + this.el.id)) {
            $('field-error-' + this.el.id).remove();
        }
    }
});

FormHandler = Class.create({
    initialize: function(form, el) {
        this.form = form;
        this.el = el;
        this.id = this.el.identify();
        this.el.observe('click', this.submit.bind(this));
    },
    submit: function(e) {
        if (e && e.stop) {
            e.stop();
        }
        if (this.el.readAttribute('form-field') && this.el.readAttribute('field-value')) {
        	var f = $(this.el.readAttribute('form-field'));
        	if (Object.isElement(f)) {
        		f.value = this.el.readAttribute('field-value');
        	}
        }
        if (this.el.readAttribute('on-submit')) {
            if (Object.isFunction(this.el.readAttribute('on-submit'))) {
                this.el.readAttribute('on-submit')();
            } else if (typeof(this.el.readAttribute('on-submit')) === 'string') {
                eval(this.el.readAttribute('on-submit'));
            }
        }
        this.form.submit();
    }
});

FormError = Class.create({
    initialize: function(container, field) {
    	this.msg = '';
        this.container = container;
        this.field = field;
    },
    destroy: function() {
        this.msg = '';
        if (this.el) {
            this.el.stopObserving();
            this.el.remove();
        }
    },
    render: function() {
        this.el = new Element('div', {
            'class': 'field-error',
            'id': 'field-error-' + this.field.id,
            'onclick': '$("' + this.field.id + '").focus();'
        });
        this.el.update(this.field.readAttribute('errormsg'));
        this.container.insert(this.el);
    }
}); 

Site.init();